home *** CD-ROM | disk | FTP | other *** search
/ Hardcore Visual Basic 5.0 (2nd Edition) / Hardcore Visual Basic 5.0 - Second Edition (1997)(Microsoft Press).iso / Code / sysmenu.cls < prev    next >
Text File  |  1997-06-14  |  5KB  |  174 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4. END
  5. Attribute VB_Name = "CSysMenu"
  6. Attribute VB_GlobalNameSpace = False
  7. Attribute VB_Creatable = True
  8. Attribute VB_PredeclaredId = False
  9. Attribute VB_Exposed = True
  10. Option Explicit
  11.  
  12. Implements ISubclass
  13. Public Event MenuClick(sItem As String, ByVal ID As Long)
  14.  
  15. Public Enum EErrorSysMenu
  16.     eeBaseSysMenu = 13240   ' CSysMenu
  17.     eeHandleNotInit         ' Handle not initialized
  18.     eeTooManyItems          ' Too many menu items
  19.     eeNoSysWindow           ' Can't get system window
  20. End Enum
  21.  
  22. Private hWnd As Long, hSysMenu As Long
  23. Private idCur As Long
  24. Private emr As EMsgResponse, pOldProc As Long
  25. Private Const idFirst As Long = 2000
  26. Private Const cMaxItem = 10
  27.  
  28. Private Type TItem
  29.     sText As String
  30.     ID As Long
  31. End Type
  32.  
  33. ' Anyone putting too many items on system menu deserves rude errors
  34.  
  35. Private aItem(1 To cMaxItem + 1) As TItem
  36.  
  37. #If fComponent = 0 Then
  38. Private Sub ErrRaise(e As Long)
  39.     Dim sText As String, sSource As String
  40.     If e > 1000 Then
  41.     
  42.         sSource = App.ExeName & ".CSysMenu"
  43.         Select Case e
  44.         Case eeHandleNotInit
  45.             sText = "Add/RemoveItem: Handle not initialized"
  46.         Case eeTooManyItems
  47.             sText = "AddItem: Too many menu items"
  48.         Case eeNoSysWindow
  49.             sText = "Create: Can't get system window"
  50.         End Select
  51.         Err.Raise e Or vbObjectError, sSource, sText
  52.     Else
  53.         ' Raise standard Visual Basic error
  54.         Err.Raise e, sSource
  55.     End If
  56. End Sub
  57. #End If
  58.  
  59. Private Sub Class_Initialize()
  60.     idCur = idFirst
  61. End Sub
  62.  
  63. Private Sub Class_Terminate()
  64.     Destroy
  65. End Sub
  66.  
  67. Sub Create(hWndA As Long)
  68.     ' Get handle of system menu
  69.     hSysMenu = GetSystemMenu(hWndA, 0&)
  70.     If hSysMenu = hNull Then ErrRaise eeNoSysWindow
  71.     hWnd = hWndA
  72.     AttachMessage Me, hWndA, WM_SYSCOMMAND
  73. End Sub
  74.  
  75. Sub Destroy()
  76.     Dim i As Integer
  77.     ' Remove all the menu items
  78.     i = 1
  79.     Do While aItem(i).ID
  80.         Call RemoveMenu(hSysMenu, aItem(i).ID, MF_BYCOMMAND)
  81.         i = i + 1
  82.     Loop
  83.     DetachMessage Me, hWnd, WM_SYSCOMMAND
  84.     hWnd = hNull
  85. End Sub
  86.  
  87. Property Get Identifier(i As Integer) As Long
  88.     Identifier = aItem(i).ID
  89. End Property
  90.  
  91. Property Get Text(i As Integer) As String
  92.     Text = aItem(i).sText
  93. End Property
  94.  
  95. Function AddItem(sItem As String) As Long
  96.     If hWnd = hNull Then
  97.         ErrRaise eeHandleNotInit
  98.     End If
  99.     ' Append the new menu item or separator
  100.     idCur = idCur + 10
  101.     If sItem = sEmpty Or sItem = "-" Then
  102.         Call AppendMenu(hSysMenu, MF_SEPARATOR Or MF_BYCOMMAND, idCur, 0&)
  103.     Else
  104.         Call AppendMenu(hSysMenu, MF_BYCOMMAND, idCur, sItem)
  105.     End If
  106.     ' Insert item
  107.     Dim i As Integer
  108.     For i = 1 To cMaxItem
  109.         If aItem(i).ID = 0 Then
  110.             aItem(i).ID = idCur
  111.             aItem(i).sText = sItem
  112.             AddItem = idCur
  113.             Exit Function
  114.         End If
  115.     Next
  116.     ErrRaise eeTooManyItems
  117. End Function
  118.  
  119. Sub RemoveItem(ID As Long)
  120.     If hWnd = hNull Then
  121.         ErrRaise eeHandleNotInit
  122.     End If
  123.     ' Find item, remove it, overwrite it
  124.     Dim f As Boolean, i As Integer, fDeleting As Boolean
  125.     i = 1
  126.     For i = 1 To cMaxItem
  127.         ' Remove reference from vector
  128.         If aItem(i).ID = ID Then
  129.             f = RemoveMenu(hSysMenu, ID, MF_BYCOMMAND)
  130.             fDeleting = True
  131.         End If
  132.         ' Overwrite deleted item
  133.         If fDeleting Then
  134.             aItem(i).ID = aItem(i + 1).ID
  135.             aItem(i).sText = aItem(i + 1).sText
  136.         End If
  137.     Next
  138. End Sub
  139.  
  140. ' Interface window procedure method
  141. Private Function ISubclass_WindowProc(ByVal hWnd As Long, _
  142.                                       ByVal iMsg As Long, _
  143.                                       ByVal wParam As Long, _
  144.                                       ByVal lParam As Long) As Long
  145.     ' Assume original WindowProc will handle
  146.     emr = emrPostProcess
  147.     ' Subclasser should never call unless it's our message
  148.     BugAssert iMsg = WM_SYSCOMMAND
  149.     ' Ignore everything except system commands
  150.     If wParam <= 3000 Then
  151.         ' Check IDs and raise event if found
  152.         Dim i As Long
  153.         For i = 1 To cMaxItem
  154.             If aItem(i).ID = 0 Then Exit For
  155.             If wParam = aItem(i).ID Then
  156.                 RaiseEvent MenuClick(aItem(i).sText, aItem(i).ID)
  157.                 ' We've finished so original WindowProc not needed
  158.                 emr = emrConsume
  159.                 Exit Function
  160.             End If
  161.         Next
  162.     End If
  163. End Function
  164.  
  165. ' Interface properties
  166. Private Property Get ISubclass_MsgResponse() As EMsgResponse
  167.     ISubclass_MsgResponse = emr
  168. End Property
  169. Private Property Let ISubclass_MsgResponse(ByVal emrA As EMsgResponse)
  170.     emr = emrA
  171. End Property
  172. '
  173.  
  174.